package main

import "go-leetcode/leetcode/utils"

// 25. K 个一组翻转链表

func main() {
	node := utils.GetListNodeByArray([]int{1, 2, 3, 4, 5})
	k := 3
	group := reverseKGroup(node, k)

	for group != nil {
		print(group.Val, "->")
		group = group.Next
	}
}

func reverseKGroup1(head *utils.ListNode, k int) *utils.ListNode { // 2025/03/09 练习
	var myReverseList func(node *utils.ListNode) *utils.ListNode
	myReverseList = func(node *utils.ListNode) *utils.ListNode {
		var newNode *utils.ListNode
		for node != nil {
			tempNext := node.Next
			node.Next = newNode
			newNode = node
			node = tempNext
		}
		return newNode
	}

	dummy := &utils.ListNode{Next: head}

	dummyLast := dummy
	prev := dummy.Next

	for head != nil {
		for i := 0; i < k-1; i++ {
			if head.Next == nil {
				return dummy.Next
			}
			head = head.Next
			prev = prev.Next
		}

		tempPrev := prev.Next
		prev.Next = nil

		prev = tempPrev
		head = tempPrev

		dummyLast.Next = myReverseList(dummyLast.Next)
		for i := 0; i < k; i++ {
			dummyLast = dummyLast.Next
		}
		dummyLast.Next = head
	}

	return dummy.Next
}

//
//
//
//
//
//
func reverseKGroup(head *utils.ListNode, k int) *utils.ListNode {
	reverseList := func(node *utils.ListNode) *utils.ListNode {
		var newHead *utils.ListNode
		for node != nil {
			newNode := node
			node = node.Next

			newNode.Next = newHead
			newHead = newNode
		}
		return newHead
	}

	dummy := &utils.ListNode{
		Next: head,
	}

	dummyLast := dummy
	prev := dummy.Next

	for head != nil {
		for i := 0; i < k-1; i++ {
			if head.Next == nil {
				return dummy.Next
			}
			prev = prev.Next
			head = head.Next
		}
		tempPrev := prev.Next
		prev.Next = nil
		prev = tempPrev
		head = prev

		dummyLast.Next = reverseList(dummyLast.Next)
		for i := 0; i < k; i++ {
			dummyLast = dummyLast.Next
		}
		dummyLast.Next = head
	}

	return dummy.Next
}

func oldReverseKGroup(head *utils.ListNode, k int) *utils.ListNode {
	if k == 1 {
		return head
	}
	prev := head

	for i := 1; i < k; i++ {
		if prev == nil || prev.Next == nil { // 说明不足k，不翻转了
			return head
		}
		prev = prev.Next
	}
	appendNodes := prev.Next
	prev.Next = nil

	// head指向头，prev指向尾， 翻转后，prev指向头，head指向尾
	var point1 *utils.ListNode
	point2 := head
	for point2 != nil {
		next := point2.Next
		point2.Next = point1
		point1 = point2
		point2 = next
	}

	head.Next = reverseKGroup(appendNodes, k)

	return prev
}

// 给你链表的头节点 head ，每 k 个节点一组进行翻转，请你返回修改后的链表。
//
//k 是一个正整数，它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍，那么请将最后剩余的节点保持原有顺序。
//
//你不能只是单纯的改变节点内部的值，而是需要实际进行节点交换。
//
//示例 1：
//
//输入：head = [1,2,3,4,5], k = 2
//输出：[2,1,4,3,5]
//示例 2：
//
//输入：head = [1,2,3,4,5], k = 3
//输出：[3,2,1,4,5]
//
//提示：
//链表中的节点数目为 n
//1 <= k <= n <= 5000
//0 <= Node.val <= 1000
//
//进阶：你可以设计一个只用 O(1) 额外内存空间的算法解决此问题吗？
